package com.attendance.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.crypto.digest.BCrypt;
import com.attendance.common.BusinessException;
import com.attendance.dto.request.*;
import com.attendance.dto.response.LoginResponse;
import com.attendance.entity.User;
import com.attendance.entity.Role;
import com.attendance.mapper.UserMapper;
import com.attendance.mapper.RoleMapper;
import com.attendance.service.UserService;
import com.attendance.utils.JwtUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.util.Objects;
import java.util.concurrent.TimeUnit;

@Slf4j
@Service
public class UserServiceImpl implements UserService {
    
    @Autowired
    private UserMapper userMapper;
    
    @Autowired
    private JwtUtil jwtUtil;
    
    @Autowired
    private StringRedisTemplate redisTemplate;
    
    @Autowired
    private RoleMapper roleMapper;
    
    @Autowired
    private PasswordEncoder passwordEncoder;
    
    @Override
    public LoginResponse login(LoginRequest request) {
        // 查询用户
        User user = userMapper.selectOne(
            new LambdaQueryWrapper<User>()
                .eq(User::getUsername, request.getUsername())
        );
        
        if (user == null) {
            throw new BusinessException("用户不存在");
        }
        
        // 验证密码
        if (!BCrypt.checkpw(request.getPassword(), user.getPassword())) {
            throw new BusinessException("密码错误");
        }
        
        // 检查用户状态
        if (user.getStatus() == 0) {
            throw new BusinessException("用户已被禁用");
        }
        
        // 查询用户角色
        Role role = roleMapper.selectOne(
            new LambdaQueryWrapper<Role>()
                .eq(Role::getId, user.getRoleId())
        );
        if (role == null) {
            throw new RuntimeException("用户角色不存在");
        }

        // 根据请求来源和用户角色进行验证
        String requestSource = request.getRequestSource(); // 从请求头或其他方式获取请求来源
        boolean isFromAdminClient = "admin".equals(requestSource);
        boolean isAdmin = "ADMIN".equals(role.getCode());
        
        if (isFromAdminClient && !isAdmin) {
            throw new BusinessException("非管理员用户不能登录管理端");
        }
        if (!isFromAdminClient && isAdmin) {
            throw new BusinessException("管理员用户请使用管理端登录");
        }
        
        // 生成token
        String token = jwtUtil.generateToken(user.getUsername());
        
        // 存储到Redis，设置过期时间
        redisTemplate.opsForValue().set(
            "token:" + user.getUsername(),
            token,
            24,
            TimeUnit.HOURS
        );
        
        // 构建响应
        LoginResponse response = new LoginResponse();
        response.setToken(token);
        
        LoginResponse.UserInfoResponse userInfo = new LoginResponse.UserInfoResponse();
        BeanUtil.copyProperties(user, userInfo);
        userInfo.setRoleCode(role.getCode());
        userInfo.setRoleName(role.getName());
        response.setUserInfo(userInfo);
        
        return response;
    }
    
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void register(RegisterRequest request) {
        // 检查用户名是否已存在
        if (userMapper.selectCount(
            new LambdaQueryWrapper<User>()
                .eq(User::getUsername, request.getUsername())
        ) > 0) {
            throw new BusinessException("用户名已存在");
        }
        
        // 查询默认角色（USER）
        Role defaultRole = roleMapper.selectOne(
            new LambdaQueryWrapper<Role>()
                .eq(Role::getCode, "USER")
                .eq(Role::getStatus, 1)  // 确保角色是启用状态
        );
        if (defaultRole == null) {
            throw new BusinessException("系统错误：默认用户角色不存在或未启用");
        }
        
        // 创建新用户
        User user = new User();
        BeanUtil.copyProperties(request, user);
        user.setPassword(BCrypt.hashpw(request.getPassword()));
        user.setRoleId(defaultRole.getId());
        user.setStatus(1);  // 设置用户状态为启用
        
        try {
            userMapper.insert(user);
        } catch (Exception e) {
            log.error("注册用户失败", e);
            throw new BusinessException("注册失败，请稍后重试");
        }
    }
    
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updatePassword(UpdatePasswordRequest request, String username) {
        // 查询用户
        User user = userMapper.selectOne(
            new LambdaQueryWrapper<User>()
                .eq(User::getUsername, username)
        );
        
        if (user == null) {
            throw new BusinessException("用户不存在");
        }
        
        // 验证旧密码
        if (!BCrypt.checkpw(request.getOldPassword(), user.getPassword())) {
            throw new BusinessException("旧密码错误");
        }
        
        // 验证新密码与确认密码是否一致
        if (!Objects.equals(request.getNewPassword(), request.getConfirmPassword())) {
            throw new BusinessException("新密码与确认密码不一致");
        }
        
        // 更新密码
        User updateUser = new User();
        updateUser.setId(user.getId());
        updateUser.setPassword(BCrypt.hashpw(request.getNewPassword()));
        
        try {
            userMapper.updateById(updateUser);
        } catch (Exception e) {
            log.error("修改密码失败", e);
            throw new BusinessException("修改密码失败，请稍后重试");
        }
    }
    
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateUserPassword(UserPasswordUpdateRequest request) {
        // 查询用户是否存在
        User user = userMapper.selectById(request.getId());
        if (user == null) {
            throw new BusinessException("用户不存在");
        }
        
        // 更新密码
        User updateUser = new User();
        updateUser.setId(request.getId());
        updateUser.setPassword(BCrypt.hashpw(request.getNewPassword()));
        
        try {
            userMapper.updateById(updateUser);
        } catch (Exception e) {
            log.error("修改密码失败", e);
            throw new BusinessException("修改密码失败，请稍后重试");
        }
    }
    
    @Override
    public void logout(String username) {
        redisTemplate.delete("token:" + username);
    }
    
    @Override
    public IPage<User> queryUsers(UserQueryRequest request) {
        LambdaQueryWrapper<User> wrapper = new LambdaQueryWrapper<>();
        
        // 添加查询条件
        wrapper.like(StringUtils.hasText(request.getUsername()), User::getUsername, request.getUsername())
            .like(StringUtils.hasText(request.getRealName()), User::getRealName, request.getRealName())
            .like(StringUtils.hasText(request.getEmail()), User::getEmail, request.getEmail())
            .like(StringUtils.hasText(request.getPhone()), User::getPhone, request.getPhone())
            .eq(request.getStatus() != null, User::getStatus, request.getStatus());
        
        // 创建分页对象，直接使用前端传来的页码（与角色管理保持一致）
        Page<User> page = new Page<>(request.getPageNum(), request.getPageSize());
        
        // 执行分页查询
        IPage<User> userPage = userMapper.selectPage(page, wrapper);
        
        // 查询并设置角色信息
        userPage.getRecords().forEach(user -> {
            Role role = roleMapper.selectById(user.getRoleId());
            if (role != null) {
                user.setRole(role);
            }
        });
        
        return userPage;
    }
    
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateUser(UserUpdateRequest request) {
        // 检查用户是否存在
        User user = userMapper.selectById(request.getId());
        if (user == null) {
            throw new BusinessException("用户不存在");
        }
        
        // 更新用户信息
        User updateUser = new User();
        BeanUtil.copyProperties(request, updateUser);
        
        try {
            userMapper.updateById(updateUser);
        } catch (Exception e) {
            log.error("更新用户信息失败", e);
            throw new BusinessException("更新用户信息失败，请稍后重试");
        }
    }
    
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void deleteUser(Long id) {
        // 检查用户是否存在
        User user = userMapper.selectById(id);
        if (user == null) {
            throw new BusinessException("用户不存在");
        }
        
        // 禁止删除管理员账号
        if ("admin".equals(user.getUsername())) {
            throw new BusinessException("不能删除管理员账号");
        }
        
        try {
            userMapper.deleteById(id);
            // 如果用户已登录，清除其token
            redisTemplate.delete("token:" + user.getUsername());
        } catch (Exception e) {
            log.error("删除用户失败", e);
            throw new BusinessException("删除用户失败，请稍后重试");
        }
    }
    
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void enableUser(Long id) {
        updateUserStatus(id, 1);
    }
    
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void disableUser(Long id) {
        // 检查是否为管理员账号
        User user = userMapper.selectById(id);
        if (user == null) {
            throw new BusinessException("用户不存在");
        }
        
        // 禁止禁用管理员账号
        if ("admin".equals(user.getUsername())) {
            throw new BusinessException("不能禁用管理员账号");
        }
        
        updateUserStatus(id, 0);
        // 清除用户token
        redisTemplate.delete("token:" + user.getUsername());
    }
    
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void setUserRole(UserRoleRequest request) {
        // 检查用户是否存在
        User user = userMapper.selectById(request.getUserId());
        if (user == null) {
            throw new BusinessException("用户不存在");
        }

        // 检查角色是否存在
        Role role = roleMapper.selectById(request.getRoleId());
        if (role == null) {
            throw new BusinessException("角色不存在");
        }

        // 不允许修改管理员的角色
        if ("admin".equals(user.getUsername())) {
            throw new BusinessException("不能修改管理员的角色");
        }

        // 更新用户角色
        User updateUser = new User();
        updateUser.setId(request.getUserId());
        updateUser.setRoleId(request.getRoleId());

        try {
            userMapper.updateById(updateUser);
            // 清除用户token，强制用户重新登录以获取新的角色信息
            redisTemplate.delete("token:" + user.getUsername());
        } catch (Exception e) {
            log.error("设置用户角色失败", e);
            throw new BusinessException("设置用户角色失败，请稍后重试");
        }
    }
    
    private void updateUserStatus(Long id, Integer status) {
        User user = userMapper.selectById(id);
        if (user == null) {
            throw new BusinessException("用户不存在");
        }
        
        User updateUser = new User();
        updateUser.setId(id);
        updateUser.setStatus(status);
        
        try {
            userMapper.updateById(updateUser);
        } catch (Exception e) {
            log.error("更新用户状态失败", e);
            throw new BusinessException("更新用户状态失败，请稍后重试");
        }
    }
} 